/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2025-03-21 14:34:06
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2025-03-21 21:09:29
 * @FilePath: /lesson/Thread_ring_queue/Ring_queue.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include<iostream>
#include<vector>
#include<string>
#include<semaphore.h>
#include<pthread.h>


//using namespace std;

template<typename T>
class RingQueue
{
private:
    void P(sem_t &s)
    {
        sem_wait(&s);// sem_wait() 对信号量--
    }
    void V(sem_t &s)
    {
        sem_post(&s);// sem_post() 对信号量++
    }

public:
    RingQueue(int max_cap)
    : _ringqueue(max_cap),_max_cap(max_cap),_c_step(0),_p_step(0)
    {
        sem_init(&_data_sem,0,0);
        sem_init(&_space_sem,0,max_cap);

        pthread_mutex_init(&_c_mutex,nullptr);
        pthread_mutex_init(&_p_mutex,nullptr);
    }

    void Push(const T& in)
    {
        // 进队列，先申请空间！
        P(_space_sem);
        pthread_mutex_lock(&_p_mutex);
        _ringqueue[_p_step]=in;
        _p_step++;
        _p_step%=_max_cap;
        pthread_mutex_unlock(&_p_mutex);
        V(_data_sem);
    }

    void Pop(T* out)
    {
        // 出队列，先申请空间！
        P(_data_sem);
        pthread_mutex_lock(&_c_mutex);
        *out=_ringqueue[_c_step];
        _c_step++;
        _c_step%=_max_cap;
        pthread_mutex_unlock(&_c_mutex);
        V(_space_sem);

    }

    ~RingQueue()
    {
        sem_destroy(&_data_sem);
        sem_destroy(&_space_sem);

        pthread_mutex_destroy(&_c_mutex);
        pthread_mutex_destroy(&_p_mutex);
    }

private:
    std::vector<T> _ringqueue;
    int _max_cap;

    int _c_step;// 生产者、消费者对应的下标
    int _p_step;

    sem_t _data_sem;// 用信号量来记录：数据和空间的多少！
    sem_t _space_sem;

    pthread_mutex_t _c_mutex;// 消费者与消费者之间的锁
    pthread_mutex_t _p_mutex;// 生产、生产之间的锁
};